Skip to content

[#503] 뷰(View)들을 UI 레이어로 분리한다#513

Closed
opficdev wants to merge 10 commits into
developfrom
chore/#503-UILayer
Closed

[#503] 뷰(View)들을 UI 레이어로 분리한다#513
opficdev wants to merge 10 commits into
developfrom
chore/#503-UILayer

Conversation

@opficdev

@opficdev opficdev commented Jun 2, 2026

Copy link
Copy Markdown
Owner

🔗 연관된 이슈

  • closed #503

🎯 의도

Presentation 레이어에 포함되어 있던 SwiftUI View를 별도 UI 레이어로 분리하여 View와 상태/비즈니스 흐름의 책임 경계를 명확히 하기 위함

📝 작업 내용

📌 요약

  • DevLogUI 모듈 추가
  • SwiftUI View 및 재사용 UI 컴포넌트를 DevLogPresentation에서 DevLogUI로 이동
  • DevLogPresentation을 ViewModel, Store, Coordinator, Routing, 화면 상태 중심으로 정리
  • App 진입 View를 DevLogApp에서 조립하도록 이동
  • DevLogUI 빌드 검증을 CI 경로에 추가
  • README, drawio, architecture harness에 UI 레이어 구조 반영

🔍 상세

  • DevLogUI 타깃을 추가하고 DevLogUI -> DevLogPresentation 의존 방향으로 구성
  • DevLogPresentation의 ViewModel을 Sources/ViewModel 단일 디렉토리에서 관리하도록 재배치
  • Coordinator, Routing, Dependency, Window 관련 타입을 Presentation 내부 역할 기준으로 재정리
  • WindowGroup에서 직접 진입하는 RootView, TodoEditorWindowView를 App 레이어로 이동
  • UI 레이어가 Domain/Core/Data/Infra/Persistence/App을 직접 알지 않도록 import 및 target dependency 정리
  • DevLogUI 생성에 맞춰 .github/workflows/build.yml의 Tuist clean 검증 경로 추가
  • docs/DevLog.drawio, docs/graph.png, README 프로젝트 구조, DevLog architecture harness 문서 갱신

📸 영상 / 이미지 (Optional)

@opficdev opficdev self-assigned this Jun 2, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

본 풀 리퀘스트는 SwiftUI 뷰와 재사용 UI 컴포넌트를 DevLogPresentation에서 분리하여 새로운 DevLogUI 모듈을 도입하고, 이에 맞춰 아키텍처 규칙 및 프로젝트 설정을 업데이트합니다. 또한 RootViewDependencies, MainViewDependencies 등의 의존성 컨테이너와 TodoViewModelFactory를 도입하여 의존성 주입 방식을 개선합니다. 리뷰 피드백에서는 DevLogApp 내부의 WindowGroup에서 RootViewDependencies를 직접 생성하여 발생할 수 있는 불필요한 재생성 문제를 지적하며 @State 프로퍼티로 관리할 것을 권장하고 있으며, RootView 내에서 dependencies에 적용된 불필요한 @State 래핑을 제거하고 let 상수로 변경하도록 제안하고 있습니다.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

networkConnectivityUseCase: container.resolve(ObserveNetworkConnectivityUseCase.self),
systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self),
trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self),
dependencies: RootViewDependencies(container: container),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

RootViewDependencies(container: container)WindowGroup 내부에서 직접 생성하여 RootView에 전달하고 있습니다. SwiftUI의 body는 여러 번 재평가(re-evaluate)될 수 있으므로, 이 과정에서 RootViewDependencies와 그 내부의 모든 Coordinator 및 ViewModel들이 매번 새로 생성되었다가 버려지는 비효율이 발생합니다.

이를 방지하기 위해 DevLogApp 구조체 내부에 @State private var rootDependencies: RootViewDependencies 프로퍼티를 선언하고, init 메서드에서 container를 사용해 한 번만 초기화한 뒤 이를 RootView에 전달하도록 수정하는 것을 권장합니다.

Suggested change
dependencies: RootViewDependencies(container: container),
dependencies: rootDependencies,

@Environment(\.diContainer) var container: DIContainer
@State var viewModel: RootViewModel
struct RootView: View {
@State private var dependencies: RootViewDependencies

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

dependencies는 내부에서 변경되지 않는 의존성 주입용 구조체이므로 @State로 선언할 필요가 없습니다. Swift의 새로운 Observation 프레임워크(@Observable)에서는 컨테이너 구조체가 단순 let 상수로 선언되어 있어도 내부의 @Observable 클래스 프로퍼티가 변경되면 SwiftUI 뷰가 올바르게 업데이트됩니다.

따라서 불필요한 @State 래핑을 제거하고 let 상수로 선언하는 것이 좋습니다.

Suggested change
@State private var dependencies: RootViewDependencies
let dependencies: RootViewDependencies

systemThemeUseCase: systemThemeUseCase,
trackAnalyticsEventUseCase: trackAnalyticsEventUseCase
))
self._dependencies = State(initialValue: dependencies)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

dependencies@State에서 일반 let 상수로 변경함에 따라, 초기화 메서드에서도 State(initialValue:) 대신 직접 대입하도록 수정합니다.

Suggested change
self._dependencies = State(initialValue: dependencies)
self.dependencies = dependencies

@opficdev opficdev closed this Jun 2, 2026
@opficdev opficdev deleted the chore/#503-UILayer branch June 2, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant